(function () {
    var canvas = document.getElementById('c'),
    c = canvas.getContext('2d'),
    w = canvas.width, h = canvas.height,
    p = [], clr, n = 200,
    // frame identifier
    counter = 0;
 
    clr = [ 'red', 'green', 'blue', 'yellow', 'purple' ];
 
    for (var i = 0; i < n; i++) {
        // generate particle with random initial velocity, radius, and color
        p.push({
            x: w/2,
            y: h/2,
            vx: Math.random()*12-6,
            vy: Math.random()*12-6,
            r: Math.random()*4+3,
            clr: Math.floor(Math.random()*clr.length)
        });
    }
 
    function frame() {
        // cover the canvas with 50% opacity (creates fading trails)
        c.fillStyle = 'rgba(0,0,0,0.5)';
        c.fillRect(0, 0, w, h);
 
        for (var i = 0; i < n; i++) {
            // reduce velocity to 99%
            p[i].vx *= 0.99;
            p[i].vy *= 0.99;
 
            // adjust position by the current velocity
            p[i].x += p[i].vx;
            p[i].y += p[i].vy;
 
            // detect collisions with the edges
            if (p[i].x < p[i].r || p[i].x > w-p[i].r) {
                // reverse velocity (direction)
                p[i].vx = -p[i].vx;
                // adjust position again (in case it already passed the edge)
                p[i].x += p[i].vx;
            }
            // see above
            if (p[i].y < p[i].r || p[i].y > h-p[i].r) {
                p[i].vy = -p[i].vy;
                p[i].y += p[i].vy;
            }
 
            // draw the circle at the new postion
            c.fillStyle = clr[p[i].clr]; // set color
            c.beginPath();
            c.arc(p[i].x, p[i].y, p[i].r, 0, Math.PI*2, false);
            c.fill();
        }
 
        var req = new XMLHttpRequest();
 
        // open a POST request to our backend
        req.open('post', 'saveframe.php');
 
        // capture the data URL of the image
        var data = canvas.toDataURL();
 
        // encode the data along with the frame identifier (and increment it)
        data = 'data=' + encodeURIComponent(data) + '&i=' + counter++;
 
        // set the appropriate request headers
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.setRequestHeader("Content-length", data.length);
        req.setRequestHeader("Connection", "close");
 
        // handle request responses
        req.onreadystatechange = function () {
            // continue if request is done
            if (req.readyState === 4 && req.status === 200) {
                // if we have not finished recording, execute another frame
                if (counter < 150) {
                    frame();
                } else {
                    alert('done');
                }
            }
        };
 
        // send the data
        req.send(data);
    }
 
    // start the whole process
    frame();
}());